package com.example.utils;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class RSA {

    /**
     * 生成 RSA 密钥对
     *
     * @return KeyPair 对象，包含公钥和私钥
     * @throws NoSuchAlgorithmException 如果不支持 RSA 算法
     */
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 获取公钥字符串
     *
     * @param publicKey 公钥对象
     * @return 公钥的 Base64 编码字符串
     */
    public static String getPublicKeyString(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    /**
     * 获取私钥字符串
     *
     * @param privateKey 私钥对象
     * @return 私钥的 Base64 编码字符串
     */
    public static String getPrivateKeyString(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }

    /**
     * RSA 公钥加密
     *
     * @param publicKey 公钥字符串
     * @param data      待加密的字符串
     * @return 加密后的字符串
     * @throws Exception 如果加密过程中出现异常
     */
    public static String encryptByPublicKey(String publicKey, String data) throws Exception {
        // System.out.println( "打印公钥"+publicKey);
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);

        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * RSA 私钥解密
     *
     * @param privateKey 私钥字符串
     * @param encryptedData 待解密的字符串
     * @return 解密后的字符串
     * @throws Exception 如果解密过程中出现异常
     */
    public static String decryptByPrivateKey(String privateKey, String encryptedData) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey priKey = keyFactory.generatePrivate(keySpec);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);

        byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decryptedData);
    }

    /**
     * RSA 私钥加密
     *
     * @param privateKey 私钥字符串
     * @param data      待加密的字符串
     * @return 加密后的字符串
     * @throws Exception 如果加密过程中出现异常
     */
    public static String encryptByPrivateKey(String privateKey, String data) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey priKey = keyFactory.generatePrivate(keySpec);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, priKey);

        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * RSA 公钥解密
     *
     * @param publicKey 公钥字符串
     * @param encryptedData 待解密的字符串
     * @return 解密后的字符串
     * @throws Exception 如果解密过程中出现异常
     */
    public static String decryptByPublicKey(String publicKey, String encryptedData) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, pubKey);

        byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decryptedData);
    }

    // 调试入口
    public static void main(String[] args) {
        try {
            KeyPair keyPair = generateKeyPair();
            String publicKeyString = getPublicKeyString(keyPair.getPublic());
            String privateKeyString = getPrivateKeyString(keyPair.getPrivate());

            System.out.println(publicKeyString);
            System.out.println(" ");
            System.out.println(privateKeyString);
            //String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4pMNiiH5+F86Piky+R8s48BeybSYT05B1DMF76y2pqzHlqBRUDIkUJ1lnd6L8yETvG2zdpO0HJGY4bKxQ94WzuJhUoXxTEOhaUdq8xFxmB5u7EKPDAxVmNKWgGmjLZJBj/ws/EE9Pe8hsGT0saxYOFp+WIEzvhMbEllLRPV0sToSD+lvIoN740rabCOUVhhpBDy5Qhk/Jw2FbUgebhwLx32O5dtARAGrMkEiYILghFCRJGBN/4p5JVSI7lDyUkE62D+xtMzMosvK9r/NasoHYvLQ5SAUJn+CWL/ZN+oMNXUHJQldwJZIZqc2dCJke8GimRh6Q7N1Vrkf4CUK425QuwIDAQAB";
            //String privateKeyString = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDikw2KIfn4Xzo+KTL5HyzjwF7JtJhPTkHUMwXvrLamrMeWoFFQMiRQnWWd3ovzIRO8bbN2k7QckZjhsrFD3hbO4mFShfFMQ6FpR2rzEXGYHm7sQo8MDFWY0paAaaMtkkGP/Cz8QT097yGwZPSxrFg4Wn5YgTO+ExsSWUtE9XSxOhIP6W8ig3vjStpsI5RWGGkEPLlCGT8nDYVtSB5uHAvHfY7l20BEAasyQSJgguCEUJEkYE3/inklVIjuUPJSQTrYP7G0zMyiy8r2v81qygdi8tDlIBQmf4JYv9k36gw1dQclCV3AlkhmpzZ0ImR7waKZGHpDs3VWuR/gJQrjblC7AgMBAAECggEASu7ccvsyq0h/QDCq+YYsd/RWxPnTx6K3lcD8LRyfWbdZ2QCTc+Tparnrcg84lMOzPcXALS7DShGDEN3iz3HDdE+dZUgEGjdhyipC/jmeKnOiNsP6gD8SDhVTjguh2n/86+w4SoMfCH0uVKLG5H39vUF8eLPeU3YJJYPfp2JQYg4VpqBzmPSwhxH9tcg8gcFxuJU8To0qN4IpL0TwKfwlGQAppDktveOhzOTuqEcpDqoPhkMcPtbayniNiM+polkME5aw9FPq51Z+IILeSVQAb8iwSe5CbCqsPRPqgfz8A2/sbezr5ymZS/FjGs5HDvPqylQNisj8ZzvqGgf+CPL6IQKBgQDouxCrpXR5kI7NW3wUi0q5WXN8Rup3IgiroO4ADPTtyqRk3s55mtkUEoXZmQELyMZZdr9LDLtwPxMj2CgmamIZJj7HVpIb7jgCvRPbCn4D0LZI6eCa248GeHVtO9oNimkhaV/AVw06hhcKg9XAAkxCm9cxss5MehyVpGL5RbBBWwKBgQD5OmmJJIfrbh/T+Qnh4jOs6jHPKHYC0DN6kOlAoHHl8rkc768JmvmS7kIK54Fv8Efy8g+a1AQWuHKoseqF5rG7CBFowjM2CbyUAJy7BWOoG8aAeVxM8V/ksmKOi4m/6STnMYoLuiDkeQxjeOV0ztdhdnfq1DldXxLD6GHfVkLsIQKBgQDb+LPxCRnmLPRMtcO5x06BkkLNnFnQ8KIxVpKeCaEXgQmRLecKmYnEpx1MZonOkZ6owMxeK1Ke7X8xygVpCfRewP9lejXvoGHgdMZnqqshAAzLLgPVWuD8xK546LFZSxHDOs3+BknCnyr4DVPjgEiETLhBiTfkoSaTaiUCZxQJMQKBgGlsRfwXEc+Ks7fsnjuIfadlIVCpotGp1DzCU4hc1hEYzSjqUjZT8cIvOox2RRBeqXCg5+zsRhZ+SzIEoFmnrgKZdRPFIfh3wecxIxsROoh/x0XNEDgT2iZZNstpRwmAy3VoRSaUwxkiAxWIrDbuz7iQbkVNJD7U2pE4GT5ptMFBAoGAfcrHlzYYuxEUEEqUux72Cym2TF4h7BBXozLBeiE98lF9XuAAO0CdEt93WW7cfGmZ6NZOC/RyU/PpD7uZG0DmxUWy/3m0PSXfuQOLih7sAWhjjDxBvaOjXQPCj6cCfIZQHlHqRoeEqj6HEpeMOScH2zHWrTfy0HemFkppTZ/0xt4=";

            String originalData = "这是要加密的数据";

            // 公钥加密，私钥解密
            String encryptedByPublicKey = encryptByPublicKey(publicKeyString, originalData);
            String decryptedByPrivateKey = decryptByPrivateKey(privateKeyString, encryptedByPublicKey);
            System.out.println("公钥加密，私钥解密：");
            System.out.println("原始数据：" + originalData);
            System.out.println("公钥加密后：" + encryptedByPublicKey);
            System.out.println("私钥解密后：" + decryptedByPrivateKey);

            // 私钥加密，公钥解密
            String encryptedByPrivateKey = encryptByPrivateKey(privateKeyString, originalData);
            String decryptedByPublicKey = decryptByPublicKey(publicKeyString, encryptedByPrivateKey);
            System.out.println("\n私钥加密，公钥解密：");
            System.out.println("原始数据：" + originalData);
            System.out.println("私钥加密后：" + encryptedByPrivateKey);
            System.out.println("公钥解密后：" + decryptedByPublicKey);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}